package model.service;

import java.io.File;
import java.io.IOException;
import it.sauronsoftware.ftp4j.FTPClient;
import it.sauronsoftware.ftp4j.FTPDataTransferException;
import it.sauronsoftware.ftp4j.FTPException;
import it.sauronsoftware.ftp4j.FTPFile;
import it.sauronsoftware.ftp4j.FTPIllegalReplyException;
import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import org.apache.commons.io.comparator.LastModifiedFileComparator;
import org.apache.log4j.PropertyConfigurator;

import model.dto.Location;


public class FtpController extends Thread{

	
	public void FTPFilesToLocalRepository(List<Location>locations,String loadingType)
	{
		
		ArrayList<Thread> threads = new ArrayList<Thread>();
		
		
		
		/*
		
		for (int i=0;i<locations.size();i++)
		{
			Location loc=locations.get(i);
		
			
			
			Runnable task=new MyRunnable(loc,loadingType);
			Thread worker = new Thread(task);
			worker.setName("Thread "+i);
			worker.start();
			threads.add(worker);
		}
		
		int running = 0;
		do {
			running = 0;
			for (Thread thread : threads) {
				if (thread.isAlive()) {
					running++;

				}
			}
			System.out.println("We have " + running + " running threads. ");
		} while (running > 0);
		System.out.println("All threads has been finished.");
		*/
		
	}

	
	
	

	public List getFilesFromFTPLocation(Location loc,String loadingType)
	{
		//PropertyConfigurator.configure("/home/hend/chub-executer/log4j.properties");
		//PropertyConfigurator.configure("E:\\workspace\\chub-executer\\log4j.properties");
		//PropertyConfigurator.configure("/home/hend/chub-executer/log4j.properties");
		//PropertyConfigurator.configure("C:\\Documents and Settings\\samy.a.omar\\workspace_3_7_2\\chub-executer\\src\\controller\\log4j.properties");
		int count=0;
		String ip = loc.getIp();
		String user = loc.getUsername();
		String pass = loc.getPass();
		String localPath=loc.getLocalPath();
		String remotePath=loc.getRemotePath();
		String days=loc.getDays();
		int numberOfDays=Integer.parseInt(days);
		String numFiles=loc.getNumOfFiles();
		int numberOfFiles=Integer.parseInt(numFiles);
		//String searchFiles=loc.getFileContains();
		String fileExtension=loc.getFileExtension();
		
		FTPClient client=new FTPClient();
		FileOutputStream fos = null;
		FileOutputStream local = null;
		boolean flag=true;
		
		List downloadedFilesList=new ArrayList();
		try{
			//System.out.println("dir 2abl el conn "+client.currentDirectory());
			client.connect(ip);
			LoggerController.logger.debug("connection established");
			//System.out.println("con est");
			client.login(user, pass);
			LoggerController.logger.debug("Logged into server");
			client.setType(FTPClient.TYPE_BINARY);
			
			System.out.println("is connected "+client.isConnected());
			
			System.out.println("dir b3d el conn "+client.currentDirectory());
			System.out.println("host "+client.getHost());
			//System.out.println("server status "+client.serverStatus());
			System.out.println("password "+client.getPassword());
			if(client.isCompressionSupported())
			{
				//Executer.logger.debug("compression is supported");
				LoggerController.logger.debug("compression is supported");
				//System.out.println("compression is supported");
			}
			else
			{    	
				client.setCompressionEnabled(true);
				LoggerController.logger.debug("compression mode is enabled");
				
			}
			if(remotePath.equals("."))
			{
				remotePath= client.currentDirectory();
			}
			System.out.println("remoooooooooooooote"+remotePath);
			File localfile = new File(localPath);  
			String[] localfiles =localfile.list();
			//File remotefile = new File(remotePath);  
			client.changeDirectory(remotePath);
			String s=client.currentDirectory();
			System.out.println("dir b3d change dir "+s);
			File remotefile = new File(s);
			//listing files on remote path
			//String[] list = client.listNames();
			FTPFile[] allRemoteFiles=client.list();
			
			//Date remoteFilesModifiedDate = null;
		
			
			//sorting files descendingly on remote side 
			FTPFile tempFile;
		for(int i=1;i<=allRemoteFiles.length;i++)
		{
			for(int j=0;j<(allRemoteFiles.length-1);j++)
			{
				if(allRemoteFiles[j+1].getModifiedDate().after(allRemoteFiles[j].getModifiedDate()))
				{
					tempFile=allRemoteFiles[j];
					allRemoteFiles[j]=allRemoteFiles[j+1];
					allRemoteFiles[j+1]=tempFile;
				}
			}
		}
			
	/*	for(int j=0;j<allRemoteFiles.length;j++)
		{
			System.out.println("alllllremotefilessssss sorted "+allRemoteFiles[j]);
		
		}*/
	//		System.out.println("list.length"+list.length);
			/*System.out.println("can read permission "+remotefile.canRead());
			System.out.println("get path  "+remotefile.getPath());
			System.out.println("exists "+remotefile.exists());
			System.out.println("is directory "+remotefile.isDirectory());
			System.out.println("parent "+remotefile.getParent());
			System.out.println("absolute path "+ remotefile.getAbsolutePath());
			System.out.println("total space "+remotefile.getTotalSpace());
		*/
			//File[] allRemoteFiles=remotefile.listFiles();
			//System.out.println("alll remote filesss "+allRemoteFiles);
			//sorting files on the remote directory descendingly
			//Arrays.sort(allRemoteFiles, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
			List<String> matchingFileNames=new ArrayList<String>();
			List<String> remoteFiles=new ArrayList<String>();
			List<Date> remoteFilesDates=new ArrayList<Date>();
	//		ArrayList<long> remoteFilesSizes=new ArrayList<long>();
			ArrayList<Long> remoteFilesSizes = new ArrayList<Long>();

			matchingFileNames=listMatchingFiles(loc);

			//getting list of file names to be downloaded after matching them with required names
			for(int x=0;x<allRemoteFiles.length;x++)
			{
				if(allRemoteFiles[x].getName().toLowerCase().contains(fileExtension.toLowerCase()))
				{
					for(int y=0;y<matchingFileNames.size();y++)
					{
						if(allRemoteFiles[x].getName().toLowerCase().contains(matchingFileNames.get(y)))	
						{
							remoteFiles.add(allRemoteFiles[x].getName());
							remoteFilesDates.add(allRemoteFiles[x].getModifiedDate());
							remoteFilesSizes.add(allRemoteFiles[x].getSize());
							//			System.out.println("remote file xxxxxx "+remoteFiles);
						}
					}
				}
			}
			
System.out.println("remote files size "+remoteFiles.size());
//Looping on files on the remote server and checking for the files to be downloaded whether they are new or they are modified
			//calling iterator function to get right number of iterations
			for (int j=0;j<iterator(remoteFiles, numberOfFiles);j++)
			{
				System.out.println("In the big for");
				//when flag is true this means that the file on the remote path doesnt exist on the local path 
				flag=true; 
				
				File temp=new File(remotePath+remoteFiles.get(j));
				File f=new File(localPath+remoteFiles.get(j));
				//long modifiedFileDate=temp.lastModified();
				//System.out.println("modified file date "+modifiedFileDate);
				Date fileDate=remoteFilesDates.get(j);


				
				for(int i=0;i<localfiles.length;i++)
				{
					//checking whether file names on both paths are matching
					if(remoteFiles.get(j).equalsIgnoreCase(localfiles[i]))
					{
						LoggerController.logger.debug("files exists at local side");
						flag=false;
						//LoggerController.logger.debug("size of "+localfiles[i]+" "+new File(localPath+localfiles[i]).length());
						//checking whether the file size on both paths is the same(the file is modified or not)
						File localFileSize=new File(localPath+localfiles[i]);
						long ss=localFileSize.length();
						System.out.println("size of local file "+new File(localPath+localfiles[i]).length());
						System.out.println("size of remote file "+remoteFilesSizes.get(j));
						if(remoteFilesSizes.get(j) != new File(localPath+localfiles[i]).length())
						{
							LoggerController.logger.debug("file on remote server has been modified(different sizes)");
							//LoggerController.logger.debug("File Date: "+fileDate);
							//checking whether the file on remote path is before the duration specified
							if(validCalender(numberOfDays).before(fileCalender(fileDate)))
							{	
								LoggerController.logger.debug("Date of file is within the right range of days");
								File old=new File(localPath+localfiles[i]);
								File toBeDeleted=new File(localPath+localfiles[i]+"tobedeleted");
								//rename the old file on local path and download the modified one
								if(old.renameTo(toBeDeleted))
								{
									LoggerController.logger.debug(old+" has been renamed");
									local = new FileOutputStream(f);
									client.download(remoteFiles.get(j),local,0,null);
									downloadedFilesList.add(remoteFiles.get(j));
									LoggerController.logger.debug("Modified file has been downloaded");
	 							}
								//delete the old file
								if(toBeDeleted.delete())
								{
									LoggerController.logger.debug(toBeDeleted+" is deleted and "+remoteFiles.get(j)+" is downloaded");
								}
							}
						}
					}
				}
				//files on server that are not downloaded before
				if(flag)
				{
					System.out.println("IN flag=true");
					System.out.println(flag);
					System.out.println(remoteFiles.get(j));
					fos = new FileOutputStream(remoteFiles.get(j));
					//System.out.println("DATE mn 7days ");
					System.out.println("DATE of file "+fileDate);
					//make sure that dates of files to be downloaded are within the right range 0f dates
					if(validCalender(numberOfDays).before(fileCalender(fileDate)))
					{
						
						System.out.println("dssdsadasdda");
						local = new FileOutputStream(f);
						
						client.download(remoteFiles.get(j),local,0,null);
						downloadedFilesList.add(remoteFiles.get(j));
						LoggerController.logger.debug(remoteFiles.get(j)+" is downloaded");
						System.out.println(remoteFiles.get(j)+" =>file is downloaded");
					}
				}
		
			}
			
		
		}
		catch(FTPDataTransferException f){
		/*
			Runnable r=new MyRunnable(loc,loadingType);
			if(count<3)
			{
				try {
					r.wait(1000L*60L);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				r.run();
				count++;
			}

			else
			{
				LoggerController.logger.debug("can't reconnect to ftp server");
	
			}
*/
		}

		catch(Exception e){
			e.printStackTrace();
		}
		finally {
			try {
				if (fos != null) {
					fos.close();
					try {
						client.disconnect(true);
					} catch (IllegalStateException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						} catch (FTPIllegalReplyException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						
					} catch (FTPException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}

			}
			catch (IOException ee) {
				ee.printStackTrace();
			}

		}
		return downloadedFilesList;
	}

	public Calendar validCalender(int numberOfDays)
	{
		Calendar c=Calendar.getInstance();
		c.add(Calendar.DATE, -1*numberOfDays);
		Date validDate=c.getTime();
		c.setTime(validDate);
		return c;
	}

	public Calendar fileCalender(Date fileDate)
	{
		Calendar cal=Calendar.getInstance();
		cal.setTime(fileDate); 
		return cal;
	}
	

	public List<String> listMatchingFiles(Location loc)
	{
		String matchingFiles=loc.getFileContains();
		String[] temp;
		List<String> fileNames=new ArrayList<String>();
		temp = matchingFiles.split("-");
		
	  	for(int i =0; i < temp.length ; i++)
	  	{
	  		fileNames.add(temp[i]);
	  		System.out.println(temp[i]);
	  	}
	  	return fileNames;
	}
	

	
	public int iterator(List<String> remoteFiles,int numberOfFiles)
	{
		int iterator=0;
		int remoteFilesSize=remoteFiles.size();
		if(remoteFilesSize<numberOfFiles)
		{
			iterator=remoteFilesSize;
		}
		else if(remoteFilesSize>numberOfFiles)
		{
			iterator=numberOfFiles;
		}
		else if(remoteFilesSize==numberOfFiles)
		{
			iterator=numberOfFiles;
		}
		System.out.println("ITERATOR "+iterator);
		return iterator;
	}
	
	
	/*public FTPFile[] lastFileModified(FTPFile[] files) {
		  Date lastMod = files[0].getModifiedDate();
		  FTPFile choice = null;
		  FTPFile[] sortedFiles;
		  for (FTPFile file : files) {
		          if (file.getModifiedDate().after(lastMod)) {
		                  choice = file;
		                  lastMod = file.getModifiedDate();
		                  
		          }
		   }
		   return choice;
		}*/

	
	
}


